Skip to content

Conversation

abrown
Copy link
Member

@abrown abrown commented May 15, 2025

Multiplication on x86 is a bit tricky: there are a few different instruction formats, some gaps, and some implicit registers holding different sets of bits (rax, rdx). This PR converts all x64 backend multiplications to use the new assembler and, in doing so, adds support for implicit registers: these are operands that need to be tracked during register allocation but may not show up in instruction disassembly. There is more that could be done to refactor these multiplication rules but that could come later.

@github-actions github-actions bot added cranelift Issues related to the Cranelift code generator cranelift:area:x64 Issues related to x64 codegen cranelift:meta Everything related to the meta-language. isle Related to the ISLE domain-specific language labels May 15, 2025
Copy link

Subscribe to Label Action

cc @cfallin, @fitzgen

This issue or pull request has been labeled: "cranelift", "cranelift:area:x64", "cranelift:meta", "isle"

Thus the following users have been cc'd because of the following labels:

  • cfallin: isle
  • fitzgen: isle

To subscribe or unsubscribe from this label, edit the .github/subscribe-to-label.json configuration file.

Learn more.

abrown added 12 commits May 19, 2025 12:28
Implicit operands are used by an instruction but not present in its
disassembled output. Instructions like `mul`, e.g., will write to the
`%rax` and `%rdx` registers, but this is all invisible in disassembly.
Implicit operands are always fixed (i.e., the register is known), but
not all fixed operands are implicit (i.e., some fixed registers _are_
disassembled).
…RetValueRegs`

Certain `mul*` instructions write to multiple registers. For register
allocation, Cranelift needs to know about all of these registers. This
change uses the pre-existing pattern of returning a `ValueRegs` type to
indicate this. This change is limited to what is needed now: the only
multi-return needed now uses two fixed registers.
This does not include any special "small immediate resizing" rules for
Winch, so the Winch disassembly tests gain a few bytes (e.g., some
immediates that _could_ fit in 8 bits are emitted as the full 32 bits).
@abrown abrown marked this pull request as ready for review May 19, 2025 19:50
@abrown abrown requested review from a team as code owners May 19, 2025 19:50
@abrown abrown requested review from cfallin and alexcrichton and removed request for a team May 19, 2025 19:50
@alexcrichton alexcrichton enabled auto-merge May 19, 2025 19:56
@alexcrichton alexcrichton added this pull request to the merge queue May 19, 2025
Merged via the queue into bytecodealliance:main with commit 7ea7ebc May 19, 2025
53 checks passed
@abrown abrown deleted the asm-mul branch May 19, 2025 20:37
alexcrichton added a commit to alexcrichton/wasmtime that referenced this pull request May 20, 2025
This commit fixes a minor regression from bytecodealliance#10782 found via fuzzing. The
regression is 16-bit immediates were forced to fit from an `i32` value
into a `u16` for 16-bit multiplication. This meant though that negative
numbers failed this conversion which meant that ISLE would panic due to
the value not being matched. This fixes the logic to first fit the i32
into an i16 and then cast that to a u16 where the first phase should hit
all the constants that are possible in Cranelift.
alexcrichton added a commit to alexcrichton/wasmtime that referenced this pull request May 20, 2025
This commit fixes a bug in the new assembler which was surfaced through
the changes in bytecodealliance#10782 but was a pre-existing issue. Specifically the
encoding of a RIP-relative addressing mode required knowing the number
of bytes at the end of an instruction but this was accidentally
hardcoded to 0. In bytecodealliance#10782 `imul` instructions were added where a
RIP-relative address mode can be used in conjunction with an immediate
which cause the RIP-relative addressing to load from the wrong address.

This bug can in theory affect other instructions in the new assembler as
well, but auditing the list of instructions it looks like `imul` is the
only one that can possibly have an immediate after a RIP-relative
addressing mode. That means that prior instructions using the new
assembler should not be affected.
alexcrichton added a commit to alexcrichton/wasmtime that referenced this pull request May 20, 2025
This commit fixes a bug in the new assembler which was surfaced through
the changes in bytecodealliance#10782 but was a pre-existing issue. Specifically the
encoding of a RIP-relative addressing mode required knowing the number
of bytes at the end of an instruction but this was accidentally
hardcoded to 0. In bytecodealliance#10782 `imul` instructions were added where a
RIP-relative address mode can be used in conjunction with an immediate
which cause the RIP-relative addressing to load from the wrong address.

This bug can in theory affect other instructions in the new assembler as
well, but auditing the list of instructions it looks like `imul` is the
only one that can possibly have an immediate after a RIP-relative
addressing mode. That means that prior instructions using the new
assembler should not be affected.
github-merge-queue bot pushed a commit that referenced this pull request May 20, 2025
* x64: Fix panic compiling 16-bit multiply-with-immediate

This commit fixes a minor regression from #10782 found via fuzzing. The
regression is 16-bit immediates were forced to fit from an `i32` value
into a `u16` for 16-bit multiplication. This meant though that negative
numbers failed this conversion which meant that ISLE would panic due to
the value not being matched. This fixes the logic to first fit the i32
into an i16 and then cast that to a u16 where the first phase should hit
all the constants that are possible in Cranelift.

* Add some more tests
github-merge-queue bot pushed a commit that referenced this pull request May 20, 2025
* x64: Fix encoding of RIP-relative addressing

This commit fixes a bug in the new assembler which was surfaced through
the changes in #10782 but was a pre-existing issue. Specifically the
encoding of a RIP-relative addressing mode required knowing the number
of bytes at the end of an instruction but this was accidentally
hardcoded to 0. In #10782 `imul` instructions were added where a
RIP-relative address mode can be used in conjunction with an immediate
which cause the RIP-relative addressing to load from the wrong address.

This bug can in theory affect other instructions in the new assembler as
well, but auditing the list of instructions it looks like `imul` is the
only one that can possibly have an immediate after a RIP-relative
addressing mode. That means that prior instructions using the new
assembler should not be affected.

* Fix testing the assembler crate

* Apply suggestions from code review

Co-authored-by: Andrew Brown <[email protected]>

---------

Co-authored-by: Andrew Brown <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cranelift:area:x64 Issues related to x64 codegen cranelift:meta Everything related to the meta-language. cranelift Issues related to the Cranelift code generator isle Related to the ISLE domain-specific language
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants